unit database_svbattle;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Grids,
  ExtCtrls, CheckLst, database_base;

type

  { TDatabaseSvBattleFrame }

  TDatabaseSvBattleFrame = class(TDatabaseBaseFrame)
    AttackMotionsGroupBox: TGroupBox;
    AttackMotionsStringGrid: TStringGrid;
    UseSvBattleCheckBox: TCheckBox;
    CompactSelectorComboBox: TComboBox;
    MagicSkillsCheckListBox: TCheckListBox;
    MagicSkillsGroupBox: TGroupBox;
    procedure AttackMotionsStringGridAfterSelection(Sender: TObject; aCol,
      aRow: Integer);
    procedure AttackMotionsStringGridDblClick(Sender: TObject);
    procedure AttackMotionsStringGridKeyUp(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure CompactSelectorComboBoxChange(Sender: TObject);
    procedure FrameResize(Sender: TObject);
    procedure Init; override;
    procedure MagicSkillsCheckListBoxItemClick(Sender: TObject; Index: integer);
    procedure UseSvBattleCheckBoxChange(Sender: TObject);
  private
    procedure UpdateAttackMotionsGrid;
    procedure InitMagicSkills;
    procedure InitCheckbox;
    procedure FillCompactSelector;
    function NeedsCompactMode: Boolean;
    procedure ResizeFull;
    procedure ResizeCompact;
  public

  end;

resourcestring
  SvBattleHeader = 'SV Battle';
  TypeStr = 'Type';
  MotionStr = 'Motion';
  ImageStr = 'Image';
  NoWeaponStr = 'No weapon';


implementation

uses
  fpjson, namehelper, attackmotionselectionformunit, LCLType;

{$R *.lfm}

{ TDatabaseSvBattleFrame }

procedure TDatabaseSvBattleFrame.Init;
begin
  UpdateAttackMotionsGrid;
  InitMagicSkills;
  InitCheckbox;
  FillCompactSelector;
  FrameResize(Self);
end;

procedure TDatabaseSvBattleFrame.MagicSkillsCheckListBoxItemClick(
  Sender: TObject; Index: integer);
var
  NewArray: TJSONArray;
  I: Integer;
begin
  NewArray := TJSONArray.Create();
  for I := 0 to MagicSkillsCheckListBox.Items.Count -1 do
    if MagicSkillsCheckListBox.Checked[I] then
      NewArray.Add(I + 1);

  Db.System.Arrays['magicSkills'] := NewArray;
end;

procedure TDatabaseSvBattleFrame.UseSvBattleCheckBoxChange(Sender: TObject);
begin
  Db.System.Booleans['optSideView'] := UseSvBattleCheckBox.Checked;
end;

procedure TDatabaseSvBattleFrame.AttackMotionsStringGridAfterSelection(
  Sender: TObject; aCol, aRow: Integer);
var
  Range: TGridRect;
begin
  with AttackMotionsStringGrid do begin
    Range := Selection;

    Range.Left := 0;
    Range.Right := 2;

    Selection := Range;
  end;
end;

procedure TDatabaseSvBattleFrame.AttackMotionsStringGridDblClick(Sender: TObject
  );
var
  FocusedWTypeId: Integer = -1;
  AttackMotions: TJSONArray = nil;
  Motion: TJSONObject;
begin
  with AttackMotionsStringGrid do
    if (Row >= 1) and (Row < RowCount) then
      FocusedWTypeId := Row - 1;


  if FocusedWTypeId >= 0 then begin
    if not Db.System.Find('attackMotions', AttackMotions) then
      Db.System.Arrays['attackMotions'] := TJSONArray.Create;

    AttackMotions := Db.System.Arrays['attackMotions'];

    while FocusedWTypeId >= AttackMotions.Count do
      AttackMotions.Add(TJSONObject.Create(['type', 0, 'weaponImageId', 0]));

    Motion := AttackMotions.Objects[FocusedWTypeId];

    if AttackMotionSelectionForm.Select(Motion.Integers['type'],
                                    Motion.Integers['weaponImageId']) then begin
      Motion.Integers['type'] := AttackMotionSelectionForm.SelectedMotionId;
      Motion.Integers['weaponImageId'] := AttackMotionSelectionForm.SelectedImageId;
      UpdateAttackMotionsGrid
    end
  end
end;

procedure TDatabaseSvBattleFrame.AttackMotionsStringGridKeyUp(Sender: TObject;
  var Key: Word; Shift: TShiftState);
begin
  if Key = VK_RETURN then
    AttackMotionsStringGridDblClick(Sender);
end;

procedure TDatabaseSvBattleFrame.CompactSelectorComboBoxChange(Sender: TObject);
begin
  if NeedsCompactMode then begin
    ResizeCompact;
  end;
end;

procedure TDatabaseSvBattleFrame.FrameResize(Sender: TObject);
begin
  if NeedsCompactMode then
    ResizeCompact
  else
    ResizeFull;
end;

procedure TDatabaseSvBattleFrame.UpdateAttackMotionsGrid;
var
  WeaponTypes: TJSONArray = nil;
  AttackMotions: TJSONArray = nil;
  Motion: TJSONObject;
  NumWeaponTypes: Integer = 1;
  Range: TGridRect;
  I: Integer;
begin
  if Db.System.Find('weaponTypes', WeaponTypes) then
    NumWeaponTypes := WeaponTypes.Count;
  Db.System.Find('attackMotions', AttackMotions);

  with AttackMotionsStringGrid do begin
    BeginUpdate;

    RowCount := NumWeaponTypes + 1;
    Cells[0, 0] := TypeStr;
    Cells[1, 0] := MotionStr;
    Cells[2, 0] := ImageStr;

    for I := 0 to WeaponTypes.Count -1 do begin
      if I = 0 then
        Cells[0, I+1] := NoWeaponStr
      else
        Cells[0, I+1] := WeaponTypes.Strings[I];

      if (AttackMotions <> nil) and (I < AttackMotions.Count) then begin
        Motion := AttackMotions.Objects[I];
        Cells[1, I+1] := GetBattleMotionTypeName(Motion.Integers['type']);
        Cells[2, I+1] := GetWeaponImageName(Motion.Integers['weaponImageId']);
      end;
    end;

    Range := Selection;
    Range.Left := 0;
    Range.Right := 2;
    Selection := Range;

    EndUpdate(True);
  end
end;

procedure TDatabaseSvBattleFrame.InitMagicSkills;
var
  SkillTypes: TJSONArray;
  MagicSkills: TJSONArray;
  I: Integer;
begin
  with MagicSkillsCheckListBox.Items do begin
    BeginUpdate;
    Clear;

    if Db.System.Find('skillTypes', SkillTypes) then
      for I := 1 to SkillTypes.Count -1 do begin
        Add(SkillTypes.Strings[I]);
        MagicSkillsCheckListBox.Checked[I - 1] := False;
      end;

    if Db.System.Find('magicSkills', MagicSkills) then
      for I := 0 to MagicSkills.Count -1 do
        MagicSkillsCheckListBox.Checked[MagicSkills.Integers[I] - 1] := True;

    EndUpdate;
  end
end;

procedure TDatabaseSvBattleFrame.InitCheckbox;
var
  UseSvBattle: Boolean = False;
  UseSvBattleJson: TJSONBoolean;
begin
  if Db.System.Find('optSideView', UseSvBattleJson) then
    UseSvBattle := UseSvBattleJson.AsBoolean;

  UseSvBattleCheckBox.Checked := UseSvBattle;
end;

procedure TDatabaseSvBattleFrame.FillCompactSelector;
begin
  with CompactSelectorComboBox.Items do begin
    BeginUpdate;
    Clear;

    Add(AttackMotionsGroupBox.Caption);
    Add(MagicSkillsGroupBox.Caption);

    EndUpdate;
  end;
  CompactSelectorComboBox.ItemIndex := 0;
end;

function TDatabaseSvBattleFrame.NeedsCompactMode: Boolean;
begin
  Result := Width < 400;
end;

procedure TDatabaseSvBattleFrame.ResizeFull;
var
  Margin: Integer = 8;
begin
  CompactSelectorComboBox.Visible := False;

  with AttackMotionsGroupBox do begin
    Left := CompactSelectorComboBox.Left;
    Top := CompactSelectorComboBox.Top;
    Width := Self.ClientWidth * 6 div 10;
    Visible := True;

    { TODO: find a better way to preset column sizes }
    AttackMotionsStringGrid.AutoFillColumns := True;
    AttackMotionsStringGrid.AutoFillColumns := False;
  end;

  with MagicSkillsGroupBox do begin
    Left := AttackMotionsGroupBox.Left + AttackMotionsGroupBox.Width + Margin;
    Top := CompactSelectorComboBox.Top;
    Width := Self.ClientWidth - Left - Margin;
    Visible := True;
  end;
end;

procedure TDatabaseSvBattleFrame.ResizeCompact;
var
  Margin: Integer = 8;
begin
  CompactSelectorComboBox.Visible := True;

  CompactSelectorComboBox.Width := ClientWidth - CompactSelectorComboBox.Left
                                - Margin;

  with AttackMotionsGroupBox do begin
    Left := CompactSelectorComboBox.Left;
    Top := CompactSelectorComboBox.Top+CompactSelectorComboBox.Height+Margin;
    Width := Self.ClientWidth - Left - Margin;
    Height := Self.ClientHeight - Top - Margin;
    Visible := CompactSelectorComboBox.ItemIndex = 0;

    { TODO: find a better way to preset column sizes }
    AttackMotionsStringGrid.AutoFillColumns := True;
    AttackMotionsStringGrid.AutoFillColumns := False;
  end;

  with MagicSkillsGroupBox do begin
    Left := CompactSelectorComboBox.Left;
    Top := CompactSelectorComboBox.Top+CompactSelectorComboBox.Height+Margin;
    Width := Self.ClientWidth - Left - Margin;
    Height := Self.ClientHeight - Top - Margin;
    Visible := CompactSelectorComboBox.ItemIndex = 1;
  end;
end;

end.

